﻿using System.Collections.Generic;
using TMPro;
using UnityEngine;


namespace HEFramework
{
    public static class ReporterUISystem
    {
        [EntitySystem]
        public class ReporterUIAwakeSystem : AwakeSystem<ReporterUI>
        {
            protected override void Awake(ReporterUI _self)
            {
                _self.Open();
            }
        }


        [EntitySystem]
        public class ReporterUIUpdateSystem : UpdateSystem<ReporterUI>
        {
            protected override void Update(ReporterUI _self)
            {
                _self.Update();
            }
        }


        [EntitySystem]
        public class ReporterUIDestroySystem : DestroySystem<ReporterUI>
        {
            protected override void Destroy(ReporterUI _self)
            {
                _self.Close();
            }
        }


        private static void Open(this ReporterUI _self)
        {
            var uc = _self.GetScene().GetChild<UIComponent>();
            if (uc == null)
            {
                return;
            }

            uc.PushUIAsync(eUIFlag.Reporter, _ =>
            {
                _self.UIWindowBehaviour = _;
                _self.Bind();
                _self.Time = 0;
                _self.TrialReporterIndex = 0;
                _self.Clear();
                _self.Update(true);
            });
        }

        private static void Bind(this ReporterUI _self)
        {
        }

        private static void Update(this ReporterUI _self, bool _isNew = false)
        {
            if (_self.UIWindowBehaviour == null || _self.UIWindowBehaviour.State != 1)
            {
                return;
            }

            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return;
            }


            //试炼消息检测
            var trial = _self.GetSceneChild<Trial>();
            if (trial != null)
            {
                //试炼消息处理
                if (_self.TrialReporterIndex < trial.CompletedChallengeIDs.Count)
                {
                    //加上正负号
                    string message = "完成{0}，{1:+0;-0}{2}";
                    var id = trial.CompletedChallengeIDs[_self.TrialReporterIndex];
                    _self.TrialReporterIndex++;
                    var trialData = dc.LoadDataTable<DRTrial>().GetData(id);
                    var table = dc.LoadDataTable<DRReward>();
                    for (int i = 0; i < trialData.RewardIDs.Length; i++)
                    {
                        int rID = trialData.RewardIDs[i];
                        switch (rID)
                        {
                            case (int)eReward.ITEM:
                                break;
                            default:
                                message = string.Format(message, trialData.Name, trialData.RewardValues[i], table.GetData(rID).Name);
                                break;
                        }

                        _self.Reporter(message);
                    }
                }
            }


            //间隔推出消息
            _self.Time -= Time.deltaTime;
            if (_self.Time <= 0)
            {
                _self.PopMessage();
                _self.Time = 0.1f;
            }

            //展示处理
            using var temps = ListObject<ReporterObject>.Create();
            for (int i = 0; i < _self.Shows.Count; i++)
            {
                var obj = _self.Shows[i];
                switch (obj.State)
                {
                    case 0:
                        if (_self.FadeIn(obj))
                        {
                            obj.State = 1;
                        }

                        break;
                    case 1:
                        if (_self.Display(obj))
                        {
                            obj.State = 2;
                        }

                        break;
                    case 2:
                        if (_self.FadeOut(obj))
                        {
                            temps.Add(_self.Shows[i]);
                        }

                        break;
                }
            }

            //回收弹窗
            for (int i = 0; i < temps.Count; i++)
            {
                _self.Shows.Remove(temps[i]);
                _self.PushMessage(temps[i]);
            }
        }

        private static void Close(this ReporterUI _self)
        {
            if (_self.UIWindowBehaviour == null)
            {
                return;
            }

            _self.Clear();
            _self.UIWindowBehaviour.Hide();
            _self.UIWindowBehaviour = null;
        }


        public static void Reporter(this ReporterUI _self, string _message)
        {
            var obj = _self.GetObject();
            obj.Text.text = _message;
            _self.Hides.Add(obj);
        }

        private static ReporterObject GetObject(this ReporterUI _self, float _preTime = 0.4f, float _time = 2f, float _postTime = 0.5f)
        {
            var pc = _self.GetSceneChild<PrefabComponent>();
            if (pc == null)
            {
                return null;
            }

            var obj = pc.GetPrefabSyn("2d/prefabs/uiitem", "ReporterItem", false);
            var reporterObj = ObjectGenerater.Instance.Fetch<ReporterObject>();
            reporterObj.GameObject = obj;
            reporterObj.GameObject.transform.SetParent(_self.UIWindowBehaviour.GetTransform("Transform_Rect"), false);
            reporterObj.Text = obj.transform.GetChild(0).GetComponent<TMP_Text>();
            reporterObj.Text.transform.localPosition = new Vector3(30, 0, 0);
            Color color = reporterObj.Text.color;
            reporterObj.Text.color = new Color(color.r, color.g, color.b, 0);
            reporterObj.State = 0;
            reporterObj.PreTime = _preTime;
            reporterObj.Time = _time;
            reporterObj.PostTime = _postTime;
            return reporterObj;
        }

        private static void PopMessage(this ReporterUI _self)
        {
            if (_self.Hides.Count <= 0)
            {
                return;
            }

            var obj = _self.Hides[0];
            obj.GameObject.SetActive(true);


            _self.Hides.RemoveAt(0);
            _self.Shows.Add(obj);

            //最多展示7个
            if (_self.Shows.Count > 7)
            {
                obj = _self.Shows[0];
                //将最早的移除
                _self.Shows.RemoveAt(0);
                _self.PushMessage(obj);
            }
        }

        private static void PushMessage(this ReporterUI _self, ReporterObject _reporterObject)
        {
            var pc = _self.GetSceneChild<PrefabComponent>();
            if (pc == null)
            {
                return;
            }

            pc.Recycle("2d/prefabs/uiitem", "ReporterItem", _reporterObject.GameObject);
            ObjectGenerater.Instance.Recycle(_reporterObject);
        }

        private static bool FadeIn(this ReporterUI _self, ReporterObject _reporterObject, float _speed = 4f)
        {
            var text = _reporterObject.Text;

            if (text.transform.localPosition.x > 0)
            {
                float x = text.transform.localPosition.x - _speed * 20 * Time.deltaTime;
                if (x <= 0)
                {
                    x = 0;
                }

                text.transform.localPosition = new Vector3(x, 0, 0);
            }

            Color color = text.color;
            float speed = _speed;
            color.a += Time.deltaTime * speed;
            if (color.a >= 1)
            {
                color.a = 1;
            }

            _reporterObject.Text.color = color;

            if (color.a.Equals(1))
            {
                return true;
            }

            return false;
        }

        private static bool Display(this ReporterUI _self, ReporterObject _reporterObject)
        {
            _reporterObject.Time -= Time.deltaTime;
            if (_reporterObject.Time <= 0)
            {
                _reporterObject.Time = 0;
                return true;
            }

            return false;
        }

        private static bool FadeOut(this ReporterUI _self, ReporterObject _reporterObject, float _speed = 0.5f)
        {
            Color color = _reporterObject.Text.color;
            float speed = _speed;
            color.a -= Time.deltaTime * speed;
            if (color.a <= 0)
            {
                color.a = 0;
            }

            _reporterObject.Text.color = color;

            if (color.a == 0)
            {
                return true;
            }

            return false;
        }

        private static void Clear(this ReporterUI _self)
        {
            for (int i = 0; i < _self.Shows.Count; i++)
            {
                _self.PushMessage(_self.Shows[i]);
            }

            for (int i = 0; i < _self.Hides.Count; i++)
            {
                _self.PushMessage(_self.Hides[i]);
            }

            _self.Shows.Clear();
            _self.Hides.Clear();
        }
    }
}